﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DataObjects.Interfaces;
using DataObjects.Enums;

namespace DataObjects
{
    public class GameObject : BaseObject
    {
        #region Attributes
        private List<IWeapon> weaponList = new List<IWeapon>();
        private List<int> weaponSizes = new List<int>();
        private ISystem shieldSystem;

        private bool destroyed;
        private int team;

        private double maxShield;
        private double shield;
        private int hull;

        private int mapX;
        private int mapY;

        private int availablePower;
        private int weaponPower;
        private int shieldPower;
        private int enginePower;

        private Guid target;
        private int damageTaken;
        #endregion

        #region Properties
        public bool IsDestroyed
        {
            get { return destroyed; }
            internal set { destroyed = value; }
        }

        public int Team
        {
            get { return team; }
            internal set { team = value; }
        }

        public double MaxShield
        {
            get { return maxShield; }
            internal set { maxShield = value; }
        }

        public double Shield
        {
            get { return shield; }
            internal set { shield = value; }
        }

        public int Hull
        {
            get { return hull; }
            internal set { hull = value; }
        }

        public int MapX
        {
            get { return mapX; }
            internal set { mapX = value; }
        }

        public int MapY
        {
            get { return mapY; }
            internal set { mapY = value; }
        }

        public int AvailablePower
        {
            get { return availablePower; }
            internal set { availablePower = value; }
        }

        public int WeaponPower
        {
            get { return weaponPower; }
            internal set { weaponPower = value; }
        }

        public int ShieldPower
        {
            get { return shieldPower; }
            internal set { shieldPower = value; }
        }

        public int EnginePower
        {
            get { return enginePower; }
            internal set { enginePower = value; }
        }

        public Guid Target
        {
            get { return target; }
            set { target = value; }
        }

        public int DamageTaken
        {
            get { return damageTaken; }
            set { damageTaken = value; }
        }
        #endregion

        public GameObject(int team)
            : base()
        {
            this.team = team;
            Setup();
        }

        public GameObject(IBehaviour behaviour, int team)
            : base(behaviour)
        {
            this.team = team;
            Setup();
        }

        virtual protected void Setup()
        {
            maxShield = 50;
            shield = 50;
            hull = 25;

            mapX = rand.Next(100);
            mapY = rand.Next(100);

            availablePower = 10;
            weaponPower = 0;
            shieldPower = 0;
            enginePower = 0;
        }

        public void AddWeaponSystem(IWeapon weapon, int slot)
        {
            weaponList.Add(weapon);
        }

        virtual public void InitialiseNewTurn()
        {
            double shieldInc = ShieldPower * (GlobalData.Delta / 1000);

            Shield = Math.Min(Shield + shieldInc, MaxShield);

            DamageTaken = 0;
            ShieldPower = 0;
            WeaponPower = 0;
            EnginePower = 0;
        }

        virtual public void DetermineWeaponDamage()
        {
            if (DamageTaken <= 0)
                return;

            Shield -= DamageTaken;

            if (Shield < 0)
            {
                Hull += (int)Shield;
                Shield = 0;
            }

            if (Shield > 0 && Hull > 0)
            {
                int chance = 95 - DamageTaken;
                int roll = rand.Next(100);
                if (roll >= chance)
                    Hull -= 1;
            }

            if (Hull <= 0)
                IsDestroyed = true;

            if (!IsDestroyed && AvailablePower > 0)
            {
                int chance = 80;
                if (Shield > 0)
                    chance += 15;

                int roll = rand.Next(100);
                if (roll >= chance)
                    AvailablePower -= 1;
            }
        }

        virtual public void ProcessWeaponsFire()
        {
            float damage = 0f;
            foreach (IWeapon weapon in weaponList.Where(w => w.WeaponType != WeaponType.ANTI_MISSILE &&
                                                             w.WeaponType != WeaponType.ANTO_FIGHTER))
            {
                if (weapon.CanFire)
                {
                    damage += weapon.BaseDamage + WeaponPower;
                    weapon.Fired();
                }
            }

            GameMap.GetPiece(Target).DamageTaken += (int)damage;
        }

        public override string ToString()
        {
            return "Team: " + team.ToString() + " Shield: " + ((int)Shield).ToString() + "-" + Hull.ToString() + "-" + AvailablePower.ToString() + " (" + Behaviour.ToString() + ")";
        }
    }
}
